﻿using System;
using System.Xml;

namespace octalforty.Syndication.Core
{
    /// <summary>
    /// Provides a base class for aggregators.
    /// </summary>
    public abstract class AggregatorBase : IAggregator
    {
        #region Private Member Variables
        private IAggregator nextAggregator;
        #endregion

        /// <summary>
        /// Initializes a new instance of <see cref="AggregatorBase"/> class.
        /// </summary>
        protected AggregatorBase()
        {
        }

        #region IAggregator Members
        /// <summary>
        /// Gets or sets a reference to the next <see cref="IAggregator"/> in
        /// the aggregators chain.
        /// </summary>
        public virtual IAggregator NextAggregator
        {
            get { return nextAggregator; }
            set { nextAggregator = value; }
        }

        /// <summary>
        /// Aggregates <paramref name="feedDocument"/> into <paramref name="syndicationFeed"/>.
        /// </summary>
        /// <param name="feedDocument">Feed XML document.</param>
        /// <param name="syndicationFeed">Syndication feed.</param>
        /// <exception cref="ArgumentNullException">
        /// When <paramref name="feedDocument"/> is a <c>null</c> reference.
        /// </exception>
        public virtual void Aggregate(XmlDocument feedDocument, ref ISyndicationFeed syndicationFeed)
        {
            if(feedDocument == null)
                throw new ArgumentNullException("feedDocument");

            InternalAggregate(feedDocument, ref syndicationFeed);
            
            if(NextAggregator != null)
                NextAggregator.Aggregate(feedDocument, ref syndicationFeed);
        }
        #endregion

        #region Overridables
        /// <summary>
        /// Internal method, invoked from the implementation of <see cref="AggregatorBase.Aggregate"/>.
        /// </summary>
        /// <param name="feedDocument"></param>
        /// <param name="syndicationFeed"></param>
        /// <remarks>
        /// The implementation must not invoke <see cref="IAggregator.Aggregate"/> 
        /// on the <see cref="NextAggregator"/>.
        /// </remarks>
        protected abstract void InternalAggregate(XmlDocument feedDocument, ref ISyndicationFeed syndicationFeed);
        #endregion
    }
}
